#include"corner.h"
#include"corners.rh"

#define MAX 1
#define MIN 2

extern int VerbFunction(int [8][8]);

void
TCorners::SetDeepness(int d)
{
    deepness=d;
}

int
TCorners::WayViaFigura(int a,int b,int c,int d,int des[8][8])
{
    if (a<0 || a>7 || b<0 || b>7)
    {
        return false;
    }

    if(des[a][b] == 4)
    {
        return true;
    }

    if(!des[a][b])
    {
        des[a][b]=3;
    }

    if(a==c && b==d)
    {
        return true;
    }

    if ((a+1 < 7) &&
        ((des[a+1][b]==1||des[a+1][b]==2)&&(!(des[a+2][b]))) &&
        (WayViaFigura(a+2,b,c,d,des)))
    {
        return true;
    }

    if ((a-1>0) &&
        ((des[a-1][b]==1||des[a-1][b]==2)&&(!(des[a-2][b]))) &&
        (WayViaFigura(a-2,b,c,d,des)))
    {
        return true;
    }

    if ((b-1>0) &&
        ((des[a][b-1]==1||des[a][b-1]==2)&&(!(des[a][b-2]))) &&
        (WayViaFigura(a,b-2,c,d,des)))
    {
        return true;
    }

    if ((b+1<7) &&
        ((des[a][b+1]==1||des[a][b+1]==2)&&(!(des[a][b+2]))) &&
        (WayViaFigura(a,b+2,c,d,des)))
    {
        return true;
    }

    return false;
}

int
TCorners::HasWay()
  {
	 int a,b,c,d;
     a = from.x;
     b = from.y;
     c = to.x;
     d = to.y;

	 return IsWayFromTo(a,b,c,d,desk);
  }

int
TCorners::IsWayFromTo(int a,int b,int c,int d,int des[8][8])
	{
	 int f;
       if(c<0||c>7||d<0||d>7) return false;
		 if(des[c][d]) return false;
	 if((c+1<8&&a==c+1&&b==d)||
       (c-1>=0&&a==c-1&&b==d)||
       (a==c&&b==d+1&&d<7)||
       (a==c&&b==d-1&&d>0))return true;
		else
		  if(!((c+1<8&&des[c+1][d])||(c>0&&des[c-1][d])||(d+1<8&&des[c][d+1])||(d>0&&des[c][d-1]))) return false;
		  else
		  {
          int f=0;
          if(c<6&&d<8&&desk[c+1][d])f=1;
          if(c>1&&d<8&&desk[c-1][d])f=1;
          if(c<8&&d<6&&desk[c][d+1])f=1;
          if(c<7&&d>1&&desk[c][d-1])f=1;
          if (!f) return false;
          if(((a-c)%2)) return false;
          if((b%2-d%2)) return false;
			int ret=WayViaFigura(a,b,c,d,des);
			for(int i=0;i<8;i++)
			  for(int j=0;j<8;j++)
				  if(des[i][j]!=1&&des[i][j]!=2)
				  des[i][j]=0;
         return ret;
		  }
	}
void
 TCorners::Go()
	 {
	  for(int i=0;i<8;i++)
		 for(int j=0;j<8;j++)
		  {
			if(desk[i][j]!=1&&desk[i][j]!=2)
				 desk[i][j]=0;
		  }
	  desk[from.x][from.y]=0;
	  oldMyX=from.x;
	  oldMyY=from.y;
	  newMyX=to.x;
	  newMyY=to.y;
	  flagUp=0;
	  if(count<3) count+=2;
	  desk[to.x][to.y]=1;
	  TMemoryDC memdc(*dc);
	  memdc.SelectObject(*kletkaBMP);
	  TMemoryDC m(*dc);
	  m.SelectObject(*whiteBMP);
	  dc->BitBlt(from.x*50+6,from.y*50+6,kletkaBMP->Width(),kletkaBMP->Height(),memdc,0,0,SRCCOPY);
	  dc->BitBlt(to.x*50+10,to.y*50+10,whiteBMP->Width(),whiteBMP->Height(),m,0,0,SRCCOPY);
	 }
void
 TCorners::Undo()
	{
	 if(!count)throw "Это первый ход";
	 count--;
	 if(oldCompX>=0&&oldCompY>=0)
	  {
		desk[oldCompX][oldCompY]=2;
		desk[newCompX][newCompY]=0;
		desk[oldMyX][oldMyY]=1;
		desk[newMyX][newMyY]=0;
	  }
	 else throw "Можно отменить только один ход.";
	oldCompX=-1;
	oldCompY=-1;
	}

TCorners::TCorners(TWindow*p,HINSTANCE in)
	{
	 parent=p;
	 dc=new TClientDC(parent->HWindow);
	 inst=in;
	 flagUp=0;
	 count=0;
    way=1;
	 for(int i=0;i<8;i++)
		for(int j=0;j<8;j++)
		  desk[i][j]=0;
	 deskBMP=new TBitmap(inst,BITMAP_DESK);
	 blackBMP=new TBitmap(inst,BITMAP_BLACK);
	 whiteBMP=new TBitmap(inst,BITMAP_WHITE);
	 kletkaBMP=new TBitmap(inst,BITMAP_KLETKA);
	 newBlackBMP=new TBitmap(inst,BITMAP_NEW_BLACK);
	 oldKletkaBMP=new TBitmap(inst,BITMAP_OLD_KLETKA);
	 flagPlay=0;
    TDib dd("black.bmp");
	 TPalette palette(dd);
  	 dc->SelectObject(palette);
	 dc->RealizePalette();
	 for(int i=0;i<3;i++)
	  for(int j=0;j<4;j++)
		{
		 desk[i][j]=2;
		 desk[i+5][j+4]=1;
		}
	 for(int i=0;i<20;i++)
		 BMPs[i]=new TBitmap(inst,BITMAP_FIRE0+i);
    deepness=1;
	}
TCorners::~TCorners()
	{
	 delete deskBMP;
	 delete whiteBMP;
	 delete blackBMP;
	 delete kletkaBMP;
	 delete dc;
	 for(int i=0;i<20;i++) delete BMPs[i];
	}
int
 TCorners::IsEnd(int desk[8][8])
	{
	 int flag1,flag2=1;
	 flag1=1;
	 for(int i=0;i<3;i++)
	  for(int j=0;j<4;j++)
		{
		 if(desk[i][j]!=1) flag1=0;;
		 if(desk[i+5][j+4]!=2) flag2=0;
		}
	 if(flag1) return 1;
	 if(flag2) return 2;
	 return 0;
	}
void
 TCorners::Restart()
	 {
	  count=0;
	 for(int i=0;i<=7;i++)
	  for(int j=0;j<=7;j++)
		 desk[i][j]=0;
	 for(int i=0;i<3;i++)
	  for(int j=0;j<4;j++)
		{
		 desk[i][j]=2;
		 desk[i+5][j+4]=1;
		}
	  flagUp=0;
	  flagPlay=0;
	 }
void
 TCorners::From(int x,int y)
	 {
	  if(flagPlay) return;
	  int a=(x-3)/50;
	  int b=(y-3)/50;
	  if(a<0||a>7||b<0||b>7)
		  throw "Вы не попали на поле";
	  if(desk[a][b]==1)
		  {
			from.x=a;
			from.y=b;
			to.x=-1;
			to.y=-1;
		  }
		 else
		  if(desk[a][b]==2) throw "Это не ваша шашка";
			  else throw "Эта клетка пуста";

	 }
void
 TCorners::To(int x,int y)
	 {
	  int a=(x-3)/50;
	  int b=(y-3)/50;
	  if(desk[a][b]==0)
		  {
			to.x=a;
			to.y=b;
			flagPlay=0;
		  }
		 else
			if(desk[a][b]==1)
				throw 10;
			 else
				if(desk[a][b]==2) throw "Клетка занята";
	  if(HasWay()) Go();
		  else
			{
			 flagPlay=1;
			}

	 }
void
 TCorners::Draw()
	 {
		TMemoryDC memdc(*dc);
		memdc.SelectObject(*deskBMP);
		TMemoryDC m(*dc);
		m.SelectObject(*blackBMP);
		TMemoryDC mm(*dc);
		mm.SelectObject(*whiteBMP);
		dc->BitBlt(0,0,deskBMP->Width(),deskBMP->Height(),memdc,0,0,SRCCOPY);
		for(int i=0;i<8;i++)
		  for(int j=0;j<8;j++)
			 {
			  int a=desk[i][j];
			  if(a)
				 if(a==1)
					 dc->BitBlt(i*50+10,j*50+10,whiteBMP->Width(),whiteBMP->Height(),mm,0,0,SRCCOPY);
					else
					 if(a==2)
						 dc->BitBlt(i*50+10,j*50+10,blackBMP->Width(),blackBMP->Height(),m,0,0,SRCCOPY);
						else desk[i][j]=0;
			 }
	 }
void
 TCorners::Jump()
	{
	 if(flagUp)
		{
		 flagUp=0;
		 TMemoryDC mem(*dc);
		 mem.SelectObject(*whiteBMP);
		 dc->BitBlt(from.x*50+10,from.y*50+8,whiteBMP->Width(),whiteBMP->Height(),mem,0,0,SRCCOPY);
		}
		else
		  {
			flagUp=1;
			TMemoryDC mem(*dc);
			mem.SelectObject(*whiteBMP);
			dc->BitBlt(from.x*50+10,from.y*50+12,whiteBMP->Width(),whiteBMP->Height(),mem,0,0,SRCCOPY);
		  }
	}
int
 TCorners::GetWay(int&oldX,int&oldY,int&newX,int&newY)
	{
   int mas[8][8];
   for(int k=0;k<8;k++)
     for(int q=0;q<8;q++)
      {
       mas[k][q]=desk[k][q];
      }
   int best=-10000;
   int fmX,fmY,toX,toY;
   int k=0;
   int g=63;
   for(int i=0;i<12;i++)
     {
       while(k<=i)
        {
         if(g>63) throw 1;
         fmX=g%8;
         fmY=g/8;
         if(desk[fmX][fmY]==2) k++;
         g--;
        }
     for(int j=0;j<20;j++)
      {
      switch(j)
       {
        case 1: toX=fmX+1;toY=fmY;break;
        case 0: toX=fmX;toY=fmY+1;break;
        case 2: toX=fmX-1;toY=fmY;break;
        case 3: toX=fmX;toY=fmY-1;break;
        default:
           {
            toX=fmX%2+((j-4))*2%8;
            toY=fmY%2+((j-4))*2/8*2;
           }
       }
      if(IsWayFromTo(fmX,fmY,toX,toY,mas))
        {
          mas[fmX][fmY]=0;
          mas[toX][toY]=2;
          int d=CreateChild(fmX,fmY,toX,toY,mas,deepness,MIN,best);
          mas[fmX][fmY]=2;
          mas[toX][toY]=0;
          if(d>=best)
            {
             best=d;
             oldX=fmX;
             oldY=fmY;
             newX=toX;
             newY=toY;
            }
        }
      }
     }
    if(best==-1000)
        return 1;
       else
        return 0;
	}
 TCorners::CreateChild(int fmX,int fmY,int toX,int toY,int des[8][8],int deep,int MinMax,int alpha)
  {
   int mas[8][8];
   for(int k=0;k<8;k++)
     for(int q=0;q<8;q++)
       mas[k][q]=des[k][q];
   int best;
   int v;
   if(MinMax==MAX) best=-10000;
      else best=10000;
   mas[fmX][fmY]=0;
   mas[toX][toY]=MinMax;
   int flag=0;
   flag=IsEnd(mas);
   if(flag==2)
         {
          mas[fmX][fmY]=MinMax;
          mas[toX][toY]=0;
          return 1000;
         }
   if(flag==1)
         {
          mas[fmX][fmY]=MinMax;
          mas[toX][toY]=0;
          return -1000;
         }
   if(deep==0&&MinMax==MIN)
         {
          int f=VerbFunction(mas);
          mas[fmX][fmY]=MinMax;
          mas[toX][toY]=0;
          return f;
         }
   int index;
   if(MinMax==MAX) index=MIN;
     else index=MAX;
   for(int i=0;i<12;i++)
     {
       int k=0;
       int g;
       if(MinMax==MAX) g=63;
         else g=0;
       while(k<=i)
        {
         if(g<0||g>63) throw 1;
         fmX=g%8;
         fmY=g/8;
         if(mas[fmX][fmY]==index) k++;
         if(MinMax==MAX) g--;
           else g++;
        }
     for(int j=0;j<20;j++)
      {
      switch(j)
       {
        case 1: toX=fmX+1;toY=fmY;break;
        case 0: toX=fmX;toY=fmY+1;break;
        case 2: toX=fmX-1;toY=fmY;break;
        case 3: toX=fmX;toY=fmY-1;break;
        default:
           {
            toX=fmX%2+((j-4))*2%8;
            toY=fmY%2+((j-4))*2/8*2;
           }
       }
      if(IsWayFromTo(fmX,fmY,toX,toY,mas))
        {
          if(MinMax==MAX)
             v=CreateChild(fmX,fmY,toX,toY,mas,deep,MIN,best);
            else
             v=CreateChild(fmX,fmY,toX,toY,mas,deep-1,MAX,best);
          if(MinMax==MAX)
             {
             if(v>=best)
               {
                best=v;
                if(best>alpha)
                   {
                    mas[fmX][fmY]=MinMax;
                    mas[toX][toY]=0;
                    return best;
                   }
               }
             }
            else
             {
             if(v<=best)
              {
               best=v;
               if(best<alpha) //change V to BEST
                 {
                  mas[fmX][fmY]=MinMax;
                  mas[toX][toY]=0;
                  return best;
                 }
              }
             }
        }
      }
     }
   mas[fmX][fmY]=MinMax;
   mas[toX][toY]=0;
   return best;
  }

void
 TCorners::CompGo()
	{
	 if(flagPlay) return;
	 int oldX,oldY,newX,newY;
    //if(way)
    if(oldCompX>=0)
      {
   	 TMemoryDC memdc(*dc);
	    memdc.SelectObject(*kletkaBMP);
	    TMemoryDC m(*dc);
	    m.SelectObject(*blackBMP);
	    if(desk[oldCompX][oldCompY]==0)dc->BitBlt(oldCompX*50+6,oldCompY*50+6,kletkaBMP->Width(),kletkaBMP->Height(),memdc,0,0,SRCCOPY);
	    if(desk[newCompX][newCompY]==2)dc->BitBlt(newCompX*50+10,newCompY*50+10,blackBMP->Width(),blackBMP->Height(),m,0,0,SRCCOPY);
      }
	 if(GetWay(oldX,oldY,newX,newY))
       {
        throw "I give up";
        }
	 desk[oldX][oldY]=0;
	 desk[newX][newY]=2;
	 oldCompX=oldX;
	 oldCompY=oldY;
	 newCompX=newX;
	 newCompY=newY;
	 TMemoryDC memdc(*dc);
	 TMemoryDC m(*dc);
    if(way)
      {
	    memdc.SelectObject(*oldKletkaBMP);
	    m.SelectObject(*newBlackBMP);
      }
     else
      {
	    memdc.SelectObject(*kletkaBMP);
	    m.SelectObject(*blackBMP);
      }
	 dc->BitBlt(oldX*50+6,oldY*50+6,oldKletkaBMP->Width(),kletkaBMP->Height(),memdc,0,0,SRCCOPY);
	 dc->BitBlt(newX*50+10,newY*50+10,newBlackBMP->Width(),blackBMP->Height(),m,0,0,SRCCOPY);
  	 for(int i=0;i<8;i++)
	   for(int j=0;j<8;j++)
	 	  if(desk[i][j]!=1&&desk[i][j]!=2)
	 		  desk[i][j]=0;

	 return;
	}
	 void TCorners::Play(int index)
	{
	 if(index==0)
		 {
		 TMemoryDC m(*dc);
		 m.SelectObject(*kletkaBMP);
		 dc->BitBlt(from.x*50+6,from.y*50+6,kletkaBMP->Width(),kletkaBMP->Height(),m,0,0,SRCCOPY);
		 }
	 if(index<20)
		{
		 TMemoryDC memdc(*dc);
		 memdc.SelectObject(*(BMPs[index]));
		 dc->BitBlt(to.x*50+10,to.y*50+10,40,40,memdc,0,0,SRCCOPY);
		 if(index==19)
			{
			 index=0;
			 flagPlay=0;
			 desk[to.x][to.y]=0;
			 desk[from.x][from.y]=1;
			 TMemoryDC memdc(*dc);
			 memdc.SelectObject(*kletkaBMP);
			 TMemoryDC m(*dc);
			 m.SelectObject(*whiteBMP);
			 dc->BitBlt(to.x*50+6,to.y*50+6,kletkaBMP->Width(),kletkaBMP->Height(),memdc,0,0,SRCCOPY);
			 dc->BitBlt(from.x*50+10,from.y*50+10,blackBMP->Width(),blackBMP->Height(),m,0,0,SRCCOPY);
			}
		}
	}


